// Package response
// Title  		encode.response.common.go
// Description  编码解析工具类
// Author  		alittlexincan@163.com  		2024/07/22 11:36
// Update  		alittlexincan@163.com  		2024/07/22 11:36
package response

import (
	"context"
	"encoding/json"
	"errors"
	"log"
	"net/http"

	"xincan.com.cn/tarot-go/internal/common/constants"
	"xincan.com.cn/tarot-go/internal/common/exception"
)

// CustomErrorEncoder
// Title CustomErrorEncoder
// Description 		自定义错误编码解析工具类, 拦截异常信息
// Author  			alittlexincan@163.com  								2024/07/22 11:36
// Update  			alittlexincan@163.com  								2024/07/22 11:36
// Param           	_ 						context.Context				上下文对象
// Param    		err 					error						错误
// Param    		w 						http.ResponseWriter			响应对象
func CustomErrorEncoder(_ context.Context, err error, w http.ResponseWriter) {
	w.Header().Set("Content-Type", "application/json;charset=utf-8")
	result := Failure(err)
	w.WriteHeader(codeStatus(result.Code))
	if codeErr := json.NewEncoder(w).Encode(result); codeErr != nil {
		log.Printf("捕获异常: %v", codeErr)
	}
}

// EncodeResponse
// Title    		编码解析函数
// Description   	application/json编码解析函数
// Author      		alittlexincan@163.com         	2024/07/22 11:36
// Return    		error							错误信息"
func EncodeResponse(_ context.Context, w http.ResponseWriter, response interface{}) error {
	w.Header().Set("Content-type", "application/json; charset=utf-8")

	// 错误处理, 如果response是error类型，则设置错误码
	if err, ok := response.(error); ok {

		// 运行时错误, 获取错误码、错误信息
		var runtime exception.RuntimeError
		if errors.As(err, &runtime) {
			w.WriteHeader(codeStatus(runtime.Code()))
			return json.NewEncoder(w).Encode(ResultBuilder().WithCode(runtime.Code()).WithMessage(runtime.Message()).Build())
		}

		// 业务错误, 获取错误码、错误信息
		var business exception.BusinessError
		if errors.As(err, &business) {
			w.WriteHeader(codeStatus(business.Code()))
			return json.NewEncoder(w).Encode(ResultBuilder().WithCode(business.Code()).WithMessage(business.Error()).Build())
		}
	}

	// 结果处理, 如果response是Result类型，则设置错误码、错误信息、数据
	if result, ok := response.(*Result); ok {
		w.WriteHeader(codeStatus(result.Code))
		return json.NewEncoder(w).Encode(result)
	}

	w.WriteHeader(constants.Ok.Code())
	return json.NewEncoder(w).Encode(ResultBuilder().WithCode(constants.Ok.Code()).WithMessage(constants.Ok.Message()).WithData(response).Build())

}

// codeStatus
// Title    		codeStatus
// Description   	根据错误码返回HTTP状态码, 判断是否是go内部的状态码, 如果是直接返回, 否则返回500
// - 内部net/http状态码返回: 100-599
// Author      		alittlexincan@163.com         	2024/07/22 11:36
// Update  			alittlexincan@163.com         	2024/07/22 11:36
// Param    		code 			int				错误码
// Return    		int								HTTP状态码
func codeStatus(code int) int {
	if code >= 100 && code < 599 {
		return code
	} else {
		return http.StatusInternalServerError
	}
}
